package cn.com.nes.site.service.project.impl;

import cn.com.nes.common.em.platform.PlatformEnum;
import cn.com.nes.common.exception.BusinessException;
import cn.com.nes.common.exception.IllegalBusinessException;
import cn.com.nes.common.exception.MissBusinessParameterException;
import cn.com.nes.common.util.CopyUtils;
import cn.com.nes.common.util.XzqhUtils;
import cn.com.nes.mybatis.agent.project.entity.ProjectServiceUserAreaCode;
import cn.com.nes.mybatis.agent.project.entity.ProjectServiceUserAuth;
import cn.com.nes.mybatis.agent.project.entity.TProject;
import cn.com.nes.mybatis.agent.project.mapper.ProjectServiceUserAuthMapper;
import cn.com.nes.mybatis.agent.system.entity.Department;
import cn.com.nes.mybatis.agent.system.entity.SystemXzqh;
import cn.com.nes.mybatis.agent.system.entity.TUser;
import cn.com.nes.site.controller.project.vo.*;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.bo.project.ProjectServiceUserAuthPageBO;
import cn.com.nes.site.entity.bo.project.SetServiceUserAreaCodeBO;
import cn.com.nes.site.entity.em.DeleteEnum;
import cn.com.nes.site.entity.em.project.ProjectServiceUserEnableEnum;
import cn.com.nes.site.entity.em.project.ProjectServiceUserTypeEnum;
import cn.com.nes.site.service.project.ProjectServiceUserAreaCodeService;
import cn.com.nes.site.service.project.ProjectServiceUserAuthService;
import cn.com.nes.site.service.project.TProjectService;
import cn.com.nes.site.service.project.bo.*;
import cn.com.nes.site.service.project.dto.*;
import cn.com.nes.site.service.project.handler.WorkAreaHandler;
import cn.com.nes.site.service.project.handler.WorkAreaHandlerNotUseProjectUuid;
import cn.com.nes.site.service.project.handler.WorkAreaHandlerUseProjectUuid;
import cn.com.nes.site.service.system.company.DepartmentService;
import cn.com.nes.site.service.system.region.XzqhService;
import cn.com.nes.site.service.system.region.dto.XzqhDTO;
import cn.com.nes.site.service.system.user.SystemUserService;
import cn.com.nes.site.service.system.user.bo.SaveERUserBO;
import cn.com.nes.site.service.workOrder.WorkOrderService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ProjectServiceUserAuthImpl extends ServiceImpl<ProjectServiceUserAuthMapper, ProjectServiceUserAuth> implements ProjectServiceUserAuthService, ApplicationContextAware {

    @Resource
    SystemUserService systemUserService;

    @Resource
    DepartmentService departmentService;

    @Resource
    ProjectServiceUserAreaCodeService projectServiceUserAreaCodeService;

    @Resource
    XzqhService xzqhService;

    @Resource
    WorkOrderService workOrderService;

    @Resource
    TProjectService tProjectService;

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 查询项目服务人员分页列表
     */
    @Override
    public Page<ProjectServiceUserDTO> getProjectServiceUserPage(ProjectServiceUserAuthPageBO bo) throws Exception {
        Page<ProjectServiceUserDTO> page = new Page<>(bo.getPageid(), bo.getPagesize()); // 准备分页参数
        page.setRecords(Collections.emptyList());
        page.setTotal(0);

        // 先查权限表的所有部门 -> 部门ID不为空
        List<String> departmentIdList = new ArrayList<>();
        if (StrUtil.isNotBlank(bo.getDepartmentId())) {
            departmentIdList.add(bo.getDepartmentId());
        } else {
            departmentIdList = this.getDepartmentIdList(bo.getProjectUuid());
        }

        // 如果当前项目没绑定任何人员,则返回空页
        if (CollectionUtil.isEmpty(departmentIdList)) {
            return page;
        }

        // 通过部门查用户 -> 缩小范围的用户ID
        List<Long> relateUserIdList = systemUserService.getUserIdList(departmentIdList, bo.getServiceUserName(), bo.getServiceUserPhone());

        // 如果没有任何符合条件的用户信息,返回空页
        if (CollectionUtil.isEmpty(relateUserIdList)) {
            return page;
        }
        bo.setRelateUserIdList(relateUserIdList);

        // 行政区划符合范围的auth_id
        if (StrUtil.isNotBlank(bo.getServiceAreaCode())) {
            List<Long> authIdList = projectServiceUserAreaCodeService.getAuthIdListByAreaCode(bo.getServiceAreaCode());

            // 如果没有任何符合条件的用户信息,返回空页
            if (CollectionUtil.isEmpty(authIdList)) {
                return page;
            }
            bo.setRelateUserIdList(authIdList);
        }

        // 最终查询业务人员的分页
        Page<ProjectServiceUserAuth> page1 = this.getServiceUserPage(bo);
        List<ProjectServiceUserDTO> projectServiceUserDTOS = new ArrayList<>();
        List<ProjectServiceUserAuth> projectServiceUserAuthList = page1.getRecords();

        Map<Long, TUser> userMap = getRelateUsers(bo, projectServiceUserAuthList.stream()
                .map(ProjectServiceUserAuth::getServiceUserId)
                .collect(Collectors.toList()));

        Map<String, Department> departmentMap = getRelateDepartments(bo, projectServiceUserAuthList.stream()
                .map(ProjectServiceUserAuth::getDepartmentId)
                .collect(Collectors.toList()));

        for (ProjectServiceUserAuth projectServiceUserAuth : projectServiceUserAuthList) {
            ProjectServiceUserDTO projectServiceUserDTO = ProjectServiceUserDTO.from(projectServiceUserAuth);
            if (CollUtil.isNotEmpty(userMap)) {
                projectServiceUserDTO.setServiceUserName(userMap.get(projectServiceUserDTO.getServiceUserId())
                        .getNickName());
                projectServiceUserDTO.setServiceUserPhone(userMap.get(projectServiceUserDTO.getServiceUserId())
                        .getPhone());
            }
            if (CollUtil.isNotEmpty(departmentMap)) {
                projectServiceUserDTO.setDepartmentName(departmentMap.get(projectServiceUserDTO.getDepartmentId())
                        .getDepartmentName());
            }
            projectServiceUserDTOS.add(projectServiceUserDTO);
        }
        page.setRecords(projectServiceUserDTOS);
        page.setTotal(page1.getTotal());
        return page;
    }

    // 查询当前项目下所有合作的部门
    private List<String> getDepartmentIdList(String projectUuid) {
        QueryWrapper<ProjectServiceUserAuth> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);
        queryWrapper.eq("project_uuid", projectUuid);
        queryWrapper.select("department_id");
        List<ProjectServiceUserAuth> projectServiceUserAuths = this.list(queryWrapper);

        List<String> list = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(projectServiceUserAuths)) {
            list = projectServiceUserAuths.stream()
                    .map(ProjectServiceUserAuth::getDepartmentId)
                    .distinct()
                    .collect(Collectors.toList());
        }
        return list;
    }

    private Map<String, Department> getRelateDepartments(ProjectServiceUserAuthPageBO bo,
            List<String> departmentIds) throws Exception {
        List<Department> departments = departmentService.getDepartment(departmentIds);
        if (CollUtil.isEmpty(departments)) {
            return null;
        }
        if (StrUtil.isNotEmpty(bo.getDepartmentId())) {
            departments = departments.stream()
                    .filter(department -> department.getDepartmentId().equals(bo.getDepartmentId()))
                    .collect(Collectors.toList());
        }
        Map<String, Department> departmentMap = departments.stream()
                .collect(Collectors.toMap(Department::getDepartmentId, department -> department));
        return departmentMap;
    }

    private Map<Long, TUser> getRelateUsers(ProjectServiceUserAuthPageBO bo, List<Long> userIds) throws Exception {
        List<TUser> users = systemUserService.getUsers(userIds);
        if (CollUtil.isEmpty(users)) {
            return null;
        }
        if (StrUtil.isNotEmpty(bo.getServiceUserPhone())) {
            users = users.stream()
                    .filter(user -> user.getPhone().equals(bo.getServiceUserPhone()))
                    .collect(Collectors.toList());
        }
        Map<Long, TUser> userMap = users.stream().collect(Collectors.toMap(TUser::getId, user -> user));
        return userMap;
    }

    private Page<ProjectServiceUserAuth> getServiceUserPage(ProjectServiceUserAuthPageBO bo) {
        Page<ProjectServiceUserAuth> page = new Page<>(bo.getPageid(), bo.getPagesize());
        QueryWrapper<ProjectServiceUserAuth> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);
        queryWrapper.eq("project_uuid", bo.getProjectUuid());
        queryWrapper.in("service_user_id", bo.getRelateUserIdList());
        if (StrUtil.isNotEmpty(bo.getOperateUserCompanyId())) {
            queryWrapper.eq("company_id", bo.getOperateUserCompanyId());
        }
        if (StrUtil.isNotBlank(bo.getDepartmentId())) {
            queryWrapper.eq("department_id", bo.getDepartmentId());
        }
        if (StrUtil.isNotBlank(bo.getServiceAreaCode())) {
            queryWrapper.in("id", bo.getAuthIdList());
        }
        page = (Page<ProjectServiceUserAuth>) this.page(page, queryWrapper);
        return page;
    }

    /**
     * 查询项目服务人员分页
     */
    @Override
    public Page<ProjectServiceUserDTO> getProjectServiceUserAuthPage(ProjectServiceUserAuthPageBO bo) throws Exception {
        if (PlatformEnum._easy_repair.getCode().equals(bo.getOperatePlatform())) {
            TProject project = tProjectService.getProjectByUuid(bo.getProjectUuid());
            TUser user = systemUserService.getUser(project.getCompanyId(), bo.getOperateUserId());
            bo.setDepartmentId(user.getDepartmentId());
            bo.setServiceUserType(ProjectServiceUserTypeEnum.CONSTRUCTION_PERSONNEL.getKey());
        }

        if (ObjectUtil.isNull(bo.getPageid()) || ObjectUtil.isNull(bo.getPagesize())) {
            bo.setPageid(1);
            bo.setPagesize(9999);
        }
        if (StrUtil.isNotBlank(bo.getServiceAreaCode())) {
            bo.setServiceAreaCode(XzqhUtils.getRegionCodePrefix(bo.getServiceAreaCode()));

            // 向上查找行政区划代码，直到level <= 1
            List<String> areaCodeList = new ArrayList<>();
            for (int level = XzqhUtils.getRegionLevel(bo.getServiceAreaCode()); level > 1; level--) {
                areaCodeList.add(XzqhUtils.getParentRegionCode(bo.getServiceAreaCode(), level));
            }
            bo.setServiceAreaCodeList(areaCodeList);
        }

        // 准备分页参数
        Page<ProjectServiceUserDTO> page = new Page<>(bo.getPageid(), bo.getPagesize());
        // 查询项目服务人员分页
        List<ProjectServiceUserDTO> projectServiceUserList = this.baseMapper.getProjectServiceUserAuthPage(page, bo);
        projectServiceUserAreaCodeService.setServiceUserAreaCode(projectServiceUserList);
        return page.setRecords(projectServiceUserList);
    }

    /**
     * 保存项目服务人员
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageData saveProjectServiceUser(SaveProjectServiceUserBO bo) throws Exception {
        // 校验服务人员
        validateServiceUser(bo);

        // 保存项目服务人员权限
        saveProjectServiceUserAuth(bo);

        return PageData.ok();
    }

    private void validateServiceUser(SaveProjectServiceUserBO bo) throws Exception {
        // 查询项目部门下的服务人员权限
        List<ProjectServiceUserAuth> projectServiceUserAuthList = getProjectServiceUserAuths(bo.getCompanyId(), bo.getProjectUuid(), bo.getDepartmentId());

        if (CollUtil.isNotEmpty(projectServiceUserAuthList)) {
            validateUser(bo);
            validateDuplicateServiceUser(bo, projectServiceUserAuthList);
            validateDuplicateServiceUserType(bo.getId(), bo.getServiceUserType(), bo.getEnableIdentity(), projectServiceUserAuthList);

            // 校验行政区划代码合法性
            if (CollectionUtil.isNotEmpty(bo.getAreaCodeList())) {
                ValidateProjectServiceUserAreaCodeBO validateProjectServiceUserAreaCodeBO = new ValidateProjectServiceUserAreaCodeBO();
                validateProjectServiceUserAreaCodeBO.setServiceUserId(bo.getServiceUserId());
                validateProjectServiceUserAreaCodeBO.setServiceUserType(bo.getServiceUserType());
                validateProjectServiceUserAreaCodeBO.setAreaCodeList(bo.getAreaCodeList());
                validateProjectServiceUserAreaCodeBO.setCheckType(ValidateProjectServiceUserAreaCodeBO.CHECK_TYPE_SAVE);
                validateProjectServiceUserAreaCodeBO.setProjectServiceUserAuthList(projectServiceUserAuthList);
                validateProjectServiceUserAreaCodeBO.setProjectUuid(bo.getProjectUuid());
                validateServiceUserAreaCode(validateProjectServiceUserAreaCodeBO);
            }
        }
    }

    private ProjectServiceUserAuthDTO getProjectServiceUserAuth(EnableProjectServiceUserBO bo) throws Exception {
        if (ObjectUtil.isNotNull(bo.getId())) {
            ProjectServiceUserAuthDTO projectServiceUserAuthDTO = new ProjectServiceUserAuthDTO();
            projectServiceUserAuthDTO.setProjectServiceUserAuth(this.getById(bo.getId()));
            List<ProjectServiceUserAreaCode> serviceUserAreaCodes = projectServiceUserAreaCodeService.getList(bo.getId());
            if (CollUtil.isNotEmpty(serviceUserAreaCodes)) {
                projectServiceUserAuthDTO.setProjectServiceUserAreaCodeServices(serviceUserAreaCodes);
                projectServiceUserAuthDTO.setServiceAreaCodes(serviceUserAreaCodes.stream()
                        .map(ProjectServiceUserAreaCode::getServiceAreaCode)
                        .collect(Collectors.toList()));
            }
            projectServiceUserAuthDTO.setEnableIdentity(bo.getEnableIdentity());
            return projectServiceUserAuthDTO;
        }

        return new ProjectServiceUserAuthDTO();
    }

    private List<ProjectServiceUserAuth> getProjectServiceUserAuths(String companyId, String projectId,
            String departmentId) throws Exception {
        QueryWrapper<ProjectServiceUserAuth> wrapper = new QueryWrapper<>();
        wrapper.eq("company_id", companyId);
        wrapper.eq("project_uuid", projectId);
        wrapper.eq("department_id", departmentId);
        wrapper.eq("deleted", false);
        return this.list(wrapper);
    }

    private void saveProjectServiceUserAuth(SaveProjectServiceUserBO bo) throws Exception {
        // 保存项目服务人员
        ProjectServiceUserAuth projectServiceUserAuth = new ProjectServiceUserAuth();
        projectServiceUserAuth.setId(bo.getId());
        projectServiceUserAuth.setCompanyId(bo.getCompanyId());
        projectServiceUserAuth.setProjectUuid(bo.getProjectUuid());
        projectServiceUserAuth.setDepartmentId(bo.getDepartmentId());
        projectServiceUserAuth.setServiceUserType(bo.getServiceUserType());
        projectServiceUserAuth.setServiceUserId(bo.getServiceUserId());
        projectServiceUserAuth.setEnableIdentity(bo.getEnableIdentity());
        projectServiceUserAuth.setDeleted(DeleteEnum._0.getKey());
        projectServiceUserAuth.setGmtModifiedId(bo.getOperateUserId());
        projectServiceUserAuth.setGmtModified(bo.getOperateDate());
        projectServiceUserAuth.setPhone(bo.getPhone());
        if (ObjectUtil.isNull(bo.getId())) {
            projectServiceUserAuth.setGmtCreateId(bo.getOperateUserId());
            projectServiceUserAuth.setGmtCreate(bo.getOperateDate());
        }

        if (!this.saveOrUpdate(projectServiceUserAuth)) {
            throw new Exception("新增项目服务人员失败");
        }

        // 保存项目服务人员的分包区域信息
        if (bo.hasServiceArea()) {
            SetServiceUserAreaCodeBO setServiceUserAreaCodeBO = new SetServiceUserAreaCodeBO();
            BeanUtils.copyProperties(bo, setServiceUserAreaCodeBO);
            setServiceUserAreaCodeBO.setAuthId(projectServiceUserAuth.getId());
            setServiceUserAreaCodeBO.setAreaCodeList(bo.getAreaCodeList());
            projectServiceUserAreaCodeService.setAreaCode(setServiceUserAreaCodeBO);
        }
    }

    /**
     * 启用/停用项目服务人员权限
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enableProjectServiceUserAuth(EnableProjectServiceUserBO bo) throws Exception {
        // 获取项目服务人员权限
        ProjectServiceUserAuthDTO projectServiceUserAuthDTO = getProjectServiceUserAuth(bo);

        // 校验项目服务人员权限合法性
        validateProjectServiceUserAuth(projectServiceUserAuthDTO);

        if (PlatformEnum._easy_repair.getCode().equals(bo.getOperatePlatform())) {
            TUser user = systemUserService.getUser(projectServiceUserAuthDTO.getProjectServiceUserAuth()
                    .getCompanyId(), bo.getOperateUserId());
            bo.setOperateUserId(user.getId());
        }
        // 更新服务人员启用标识
        this.updateById(projectServiceUserAuthDTO.settingEnableIdentity(bo.getOperateUserId(), bo.getOperateDate()));
    }

    /**
     * 校验项目服务人员权限
     * @param projectServiceUserAuthDTO
     */
    private void validateProjectServiceUserAuth(ProjectServiceUserAuthDTO projectServiceUserAuthDTO) throws Exception {
        ProjectServiceUserAuth projectServiceUserAuth = projectServiceUserAuthDTO.getProjectServiceUserAuth();

        // 校验服务人员权限是否有效
        validateProjectServiceUserAuth(projectServiceUserAuthDTO.getProjectServiceUserAuth());

        // 校验该服务人员权限是否设置了服务区域，未设置不可启用
        validateServiceUserHasAreaCodes(projectServiceUserAuthDTO);

        // 校验人员权限类别是否存在重复，仅施工负责人需要校验，
        List<ProjectServiceUserAuth> projectServiceUserAuthList = getProjectServiceUserAuths(projectServiceUserAuth.getCompanyId(), projectServiceUserAuth.getProjectUuid(), projectServiceUserAuth.getDepartmentId());
        if (ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey()
                .equals(projectServiceUserAuth.getServiceUserType()) && CollUtil.isNotEmpty(projectServiceUserAuthList)) {
            validateDuplicateServiceUserType(projectServiceUserAuth.getId(), projectServiceUserAuth.getServiceUserType(), projectServiceUserAuthDTO.getEnableIdentity(), projectServiceUserAuthList);
        }

        // 如果是启用 - 校验行政区划代码合法性
        if (ProjectServiceUserEnableEnum.enable.getKey().equals(projectServiceUserAuthDTO.getEnableIdentity())) {
            ValidateProjectServiceUserAreaCodeBO validateProjectServiceUserAreaCodeBO = new ValidateProjectServiceUserAreaCodeBO();
            validateProjectServiceUserAreaCodeBO.setServiceUserId(projectServiceUserAuth.getServiceUserId());
            validateProjectServiceUserAreaCodeBO.setServiceUserType(projectServiceUserAuth.getServiceUserType());
            validateProjectServiceUserAreaCodeBO.setAreaCodeList(projectServiceUserAuthDTO.getServiceAreaCodes());
            validateProjectServiceUserAreaCodeBO.setCheckType(ValidateProjectServiceUserAreaCodeBO.CHECK_TYPE_ENABLE);
            validateProjectServiceUserAreaCodeBO.setProjectServiceUserAuthList(projectServiceUserAuthList);
            validateProjectServiceUserAreaCodeBO.setProjectUuid(projectServiceUserAuth.getProjectUuid());
            validateServiceUserAreaCode(validateProjectServiceUserAreaCodeBO);
        }
    }

    /**
     * 校验项目服务人员是否重复
     * @param bo
     * @param collect
     */
    private void validateDuplicateServiceUser(SaveProjectServiceUserBO bo,
            List<ProjectServiceUserAuth> collect) throws Exception {
        List<ProjectServiceUserAuth> collect1 = collect.stream()
                .filter(projectServiceUserAuth -> !projectServiceUserAuth.getId()
                        .equals(bo.getId()) && projectServiceUserAuth.getServiceUserId()
                        .equals(bo.getServiceUserId()) && DeleteEnum._0.getKey() == projectServiceUserAuth.getDeleted())
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect1)) {
            throw new BusinessException("当前施工人员已关联到当前项目,请勿重复关联!");
        }
    }

    /**
     * 校验服务人员是否存在
     * @param vo
     */
    private void validateUser(SaveProjectServiceUserBO vo) {
        TUser user = systemUserService.getUserInfoByUserId(String.valueOf(vo.getServiceUserId()));
        if (ObjectUtil.isNull(user)) {
            throw new IllegalBusinessException("用户不存在！");
        }
    }

    /**
     * 校验服务人员类别重复
     * @param id
     * @param serviceUserType
     * @param enableIdentity
     * @param collect
     */
    private void validateDuplicateServiceUserType(Long id, Integer serviceUserType, Integer enableIdentity,
            List<ProjectServiceUserAuth> collect) throws Exception {
        List<ProjectServiceUserAuth> collect1 = collect.stream()
                .filter(projectServiceUserAuth -> !projectServiceUserAuth.getId()
                        .equals(id) && projectServiceUserAuth.getServiceUserType()
                        .equals(1) && projectServiceUserAuth.getServiceUserType()
                        .equals(serviceUserType) && projectServiceUserAuth.getEnableIdentity()
                        .equals(0) && enableIdentity.equals(0))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect1)) {
            throw new BusinessException("当前部门下存在已启用的施工负责人，请勿重复设置！");
        }
    }

    /**
     * 校验PC端配置的服务人员
     */
    private void validateServiceUserAreaCode(ValidateProjectServiceUserAreaCodeBO bo) throws Exception {
        // 如果行政区划代码为空 - 说明不用校验
        if (CollectionUtil.isEmpty(bo.getAreaCodeList())) {
            log.info("服务人员行政区划设置为空,无需再次校验");
            return;
        }
        if (ObjectUtil.isNull(bo.getServiceUserId())) {
            throw new MissBusinessParameterException("人员id");
        }
        if (ObjectUtil.isNull(bo.getServiceUserType())) {
            throw new MissBusinessParameterException("服务人员权限");
        }
        if (ObjectUtil.isNull(bo.getCheckType())) {
            throw new MissBusinessParameterException("校验类别");
        }
        if (StrUtil.isBlank(bo.getProjectUuid())) {
            throw new MissBusinessParameterException("项目uuid");
        }

        // 获取其他队友的服务配置信息列表
        List<ProjectServiceUserAuth> projectServiceUserAuthList = bo.getProjectServiceUserAuthList()
                .stream()
                .filter(n -> !n.getServiceUserId().equals(bo.getServiceUserId()))
                .collect(Collectors.toList());

        // 准备一个集合收集上限行政区划代码 - 先确定上限
        Set<String> upperLimitSet = new HashSet<>();

        // 如果是队员 且 有启用中的队长
        if (ProjectServiceUserTypeEnum.CONSTRUCTION_PERSONNEL.getKey().equals(bo.getServiceUserType())) {
            // 尝试从所有队友当中取一个【没删除、启用中、是队长】的配置信息
            ProjectServiceUserAuth captainAuthInfo = projectServiceUserAuthList.stream()
                    .filter(n -> ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey()
                            .equals(n.getServiceUserType()) && ProjectServiceUserEnableEnum.enable.getKey()
                            .equals(n.getEnableIdentity()) && ((Integer) DeleteEnum._0.getKey()).equals(n.getDeleted()))
                    .findFirst()
                    .orElse(null);
            // 如果有队长 - 和队长的行政区划代码范围比较
            if (ObjectUtil.isNotNull(captainAuthInfo)) {
                // 拿到队长的全部行政区划代码 - 包括所有子级
                upperLimitSet.addAll(this.getServiceUserAllAreaCodes(captainAuthInfo.getServiceUserId(), bo.getProjectUuid()));
            }
        }

        // 如果是队长 或 是队员但没队长 - 和项目行政区划范围比较
        if (CollectionUtil.isEmpty(upperLimitSet)) {
            TProjectDTO projectDetail = tProjectService.getProjectDetail(bo.getProjectUuid());
            if (ObjectUtil.isNull(projectDetail)) {
                throw new IllegalBusinessException("项目不存在！项目uuid:" + bo.getProjectUuid());
            }
            upperLimitSet.addAll(xzqhService.getChildAreaCodesByParentAreaCodeList(Collections.singletonList(projectDetail.getAreaCode()), true));
        }

        // 校验行政区划是否符合设置范围
        validatedServiceAreaCode(new ArrayList<>(upperLimitSet), bo.getAreaCodeList());

        // 如果是队长 - 需要和队员的全部行政区划代码比较 - 确定下限
        if (ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey()
                .equals(bo.getServiceUserType()) && CollectionUtil.isNotEmpty(projectServiceUserAuthList)) {
            // 获取当前队长的服务行政区划范围
            List<String> captainAreaCodes = xzqhService.getChildAreaCodesByParentAreaCodeList(bo.getAreaCodeList(), true);

            Map<String, String> map = new HashMap<>();
            // 筛选施工队员
            projectServiceUserAuthList = projectServiceUserAuthList.stream()
                    .filter(n -> ProjectServiceUserTypeEnum.CONSTRUCTION_PERSONNEL.getKey()
                            .equals(n.getServiceUserType()) && ProjectServiceUserEnableEnum.enable.getKey()
                            .equals(n.getEnableIdentity()) && ((Integer) DeleteEnum._0.getKey()).equals(n.getDeleted()))
                    .collect(Collectors.toList());
            // 遍历处理每一个启用队员的服务行政区划
            for (ProjectServiceUserAuth teamMemberAuthInfo : projectServiceUserAuthList) {
                // 获取施工队员配置的服务行政区划代码 - 无子级
                List<MyTeamWorkAreaDTO> teamMemberWorkAreaList = this.getTeamMemberWorkArea(Collections.singletonList(teamMemberAuthInfo.getServiceUserId()), bo.getProjectUuid());
                Set<String> lowerLimitSet = teamMemberWorkAreaList.stream()
                        .map(MyTeamWorkAreaDTO::getAreaCode)
                        .collect(Collectors.toSet());

                Set<String> areaCodeSet = lowerLimitSet.stream()
                        .filter(teamMemberServiceAreaCode -> !captainAreaCodes.contains(teamMemberServiceAreaCode))
                        .collect(Collectors.toSet());

                if (CollectionUtil.isNotEmpty(areaCodeSet)) {
                    TUser userInfo = systemUserService.getUserInfoByUserId(String.valueOf(teamMemberAuthInfo.getServiceUserId()));
                    List<SystemXzqh> systemAreaInfos = (List<SystemXzqh>) xzqhService.listByIds(areaCodeSet);
                    map.put(userInfo.getNickName(), systemAreaInfos.stream()
                            .map(SystemXzqh::getXzqhmc)
                            .collect(Collectors.joining(",")));
                }
            }

            if (CollectionUtil.isNotEmpty(map)) {
                throw new BusinessException("当前施工队长服务区域设置有误,未包含以下施工队员的行政区划:" + JSONObject.toJSONString(map));
            }
        }
    }

    /**
     * 校验服务人员的服务区域
     * @param projectServiceUserAuthDTO
     */
    private void validateServiceUserHasAreaCodes(ProjectServiceUserAuthDTO projectServiceUserAuthDTO) throws Exception {
        if (!projectServiceUserAuthDTO.hasServiceAreaCode()) {
            throw new BusinessException("未设置服务区域，不可启用！");
        }
    }

    /**
     * 删除项目服务人员
     */
    @Override
    public PageData delProjectServiceUser(DelProjectServiceUserVO vo) throws Exception {
        ProjectServiceUserAuth projectServiceUserAuth = new ProjectServiceUserAuth();
        projectServiceUserAuth.setId(vo.getId());
        projectServiceUserAuth.setDeleted(DeleteEnum._1.getKey());
        projectServiceUserAuth.setGmtModifiedId(vo.getOperateUserId());
        projectServiceUserAuth.setGmtModified(vo.getOperateDate());

        Integer rows = this.baseMapper.updateById(projectServiceUserAuth);
        if (1 != rows) {
            throw new Exception("删除项目施工队员失败");
        }

        // 删除子表数据
        projectServiceUserAreaCodeService.deleteByAuthId(vo);

        return PageData.ok();
    }

    /**
     * 查询项目服务负责人列表 - 不分页
     */
    @Override
    public List<ProjectServiceUserDTO> getConstructionSupervisorList(GetConstructionSupervisorListVO vo) {
        // 查询项目服务管理人员列表 - 不分页
        QueryWrapper<ProjectServiceUserAuth> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_uuid", vo.getProjectUuid());
        queryWrapper.eq("deleted", false);
        queryWrapper.in("service_user_type", 1);
        List<ProjectServiceUserAuth> projectServiceUserAuths = this.list(queryWrapper);
        List<ProjectServiceUserDTO> constructionSupervisorList = CopyUtils.copyList(projectServiceUserAuths, ProjectServiceUserDTO.class);

        projectServiceUserAreaCodeService.setServiceUserAreaCode(constructionSupervisorList);
        return constructionSupervisorList;
    }

    @Override
    public List<MyTeamInfoDTO> getMyTeamInfoList(GetMyTeamInfoVO vo) {
        return systemUserService.getMyTeamInfoList(vo.getEasyRepairUserId());
    }

    @Override
    public List<Map<String, String>> getMyTeamProjectList(GetMyTeamProjectVO vo) throws Exception {
        // if (!this.validateHeadAuth(vo.getEasyRepairUserId())) {
        //     throw new BusinessException("当前用户没有操作权限！");
        // }
        return this.baseMapper.getMyTeamProjectList(vo);
    }

    @Override
    public List<Map<String, Object>> getMyTeamMemberList(GetMyTeamMemberVO vo, Boolean retainCaptain) throws Exception {
        if (StrUtil.isNotBlank(vo.getAreaCode())) {
            vo.setAreaCode(XzqhUtils.getRegionCodePrefix(vo.getAreaCode()));
        }
        ProjectServiceUserAuthPageBO projectServiceUserAuthPageBO = new ProjectServiceUserAuthPageBO();
        projectServiceUserAuthPageBO.setProjectUuid(vo.getProjectUuid());
        projectServiceUserAuthPageBO.setDepartmentIdSet(this.getDepartmentIdSetByEasyRepair(vo.getEasyRepairUserId(), vo.getProjectUuid()));
        projectServiceUserAuthPageBO.setServiceAreaCode(vo.getAreaCode());
        if (retainCaptain) {
            projectServiceUserAuthPageBO.setServiceUserType(1);
        } else {
            projectServiceUserAuthPageBO.setServiceUserType(0);
        }
        projectServiceUserAuthPageBO.setEnableIdentity(ProjectServiceUserEnableEnum.enable.getKey());
        Page<ProjectServiceUserDTO> projectServiceUserAuthPage = this.getProjectServiceUserAuthPage(projectServiceUserAuthPageBO);
        List<ProjectServiceUserDTO> projectServiceUserDTOList = projectServiceUserAuthPage.getRecords();
        if (CollUtil.isNotEmpty(projectServiceUserDTOList)) {
            List<Map<String, Object>> resultMapList = new ArrayList<>();
            for (ProjectServiceUserDTO projectServiceUserDTO : projectServiceUserDTOList) {
                // 去除不符合行政区划的人员信息
                if (!checkServiceUserByAreaCode(projectServiceUserDTO, vo.getAreaCode())) continue;

                HashMap<String, Object> resultMap = new HashMap<>();
                resultMap.put("id", projectServiceUserDTO.getId());
                resultMap.put("userId", projectServiceUserDTO.getServiceUserId());
                resultMap.put("username", projectServiceUserDTO.getServiceUserName());
                resultMap.put("callCenterUserId", projectServiceUserDTO.getCallcenterUserId());
                resultMapList.add(resultMap);
            }
            return resultMapList;
        }
        return Collections.emptyList();
    }

    @Override
    public List<MyTeamWorkAreaDTO> getMyTeamWorkArea(GetMyTeamWorkAreaVO vo) throws Exception {
        // if (!this.validateHeadAuth(vo.getEasyRepairUserId())) {
        //     throw new BusinessException("当前用户没有操作权限！");
        // }
        if (5 == XzqhUtils.getRegionLevel(vo.getAreaCode())) {
            return Collections.emptyList();
        }

        //获取项目信息
        Set<String> projectUuidSet = new HashSet<>();
        if (StrUtil.isBlank(vo.getProjectUuid())) {
            // 获取当前登录人所在施工队全部项目信息
            GetMyTeamProjectVO getMyTeamProjectVO = new GetMyTeamProjectVO();
            getMyTeamProjectVO.setEasyRepairUserId(vo.getEasyRepairUserId());
            List<Map<String, String>> myTeamProjectList = this.getMyTeamProjectList(getMyTeamProjectVO);
            if (CollectionUtil.isEmpty(myTeamProjectList)) {
                log.info("当前登录人未关联任何项目");
                //                return Collections.emptyList();
            }
            projectUuidSet = myTeamProjectList.stream().map(n -> n.get("projectUuid")).collect(Collectors.toSet());
        } else {
            projectUuidSet.add(vo.getProjectUuid());
        }

        // 根据项目uuid和易修用户id获取负责的行政区划代码集合
        QueryInstallWorkAreaBO queryBO = vo.convertToBo(QueryInstallWorkAreaBO.class);
        queryBO.setEasyRepairUserId(vo.getEasyRepairUserId());
        queryBO.setProjectUuidSet(projectUuidSet);
        queryBO.setAreaCode(vo.getAreaCode());
        queryBO.setWhetherItIsUseProjectUuid(StrUtil.isNotBlank(vo.getProjectUuid()));
        return getTeamMemberWorkArea(queryBO);
    }

    // 根据项目uuid和易修用户id获取负责的行政区划代码集合
    private List<MyTeamWorkAreaDTO> getTeamMemberWorkArea(QueryInstallWorkAreaBO queryBO) throws Exception {
        // 任何角色均应该调用本接口
        //         if (!this.validateHeadAuth(easyRepairUserId)) {
        //             throw new BusinessException("当前用户没有操作权限！");
        //         }
        // 允许用户未绑定任何施工队
        //        if (CollectionUtil.isEmpty(queryBO.getProjectUuidSet())) {
        //            throw new MissBusinessParameterException("projectUuidList must not be empty");
        //        }
        if (5 == XzqhUtils.getRegionLevel(queryBO.getAreaCode())) {
            return Collections.emptyList();
        }

        WorkAreaHandler workAreaHandler = applicationContext.getBean(WorkAreaHandlerUseProjectUuid.class);
        workAreaHandler.setSuccessor(applicationContext.getBean(WorkAreaHandlerNotUseProjectUuid.class));
        Set<String> areaCodeSet = workAreaHandler.queryInstallWorkArea(queryBO);

        if (CollUtil.isEmpty(areaCodeSet)) {
            return Collections.emptyList();
        }
        // 筛选目标等级的所有行政区划代码
        Set<String> childLevelAreaCodeSet = XzqhUtils.getChildLevelAreaCodeSet(areaCodeSet, queryBO.getAreaCode());

        return xzqhService.listByIds(childLevelAreaCodeSet)
                .stream()
                .map(this::createTeamWorkAreaInfo)
                .collect(Collectors.toList());
    }

    @Override
    public Long getUserIdByProjectId(Long projectId, Long easyRepairUserId, Boolean isCaptain) {
        return this.baseMapper.getUserIdByProjectId(projectId, easyRepairUserId, isCaptain);
    }

    @Override
    public List<MyTeamWorkAreaDTO> getTeamMemberWorkArea(List<Long> teamMemberIdList, String projectUuid) {
        List<MyTeamWorkAreaDTO> myTeamWorkAreaDTOList = this.baseMapper.getTeamMemberWorkArea(teamMemberIdList, projectUuid);
        if (CollectionUtil.isEmpty(myTeamWorkAreaDTOList)) {
            return Collections.emptyList();
        }
        return myTeamWorkAreaDTOList;
    }

    @Override
    public List<String> getTeamMemberWorkAreaCode(List<Long> teamMemberIdList, String projectUuid,
            boolean getChildArea) throws Exception {
        List<MyTeamWorkAreaDTO> teamMemberWorkArea = this.getTeamMemberWorkArea(teamMemberIdList, projectUuid);
        if (CollectionUtil.isEmpty(teamMemberWorkArea)) {
            // 不报错,只返回空,表示当前队员在当前项目下未配置服务区域
            return Collections.emptyList();
        }

        // 过滤出数据库保存的节点信息
        Set<String> areaCodeSetCache = teamMemberWorkArea.stream()
                .map(MyTeamWorkAreaDTO::getAreaCode)
                .collect(Collectors.toSet());
        if (!getChildArea) {
            return new ArrayList<>(areaCodeSetCache);
        }

        // 过滤出最末级节点
        Set<String> areaCodeSet = new HashSet<>(areaCodeSetCache);
        areaCodeSet.removeIf(areaCode -> areaCodeSetCache.stream()
                .anyMatch(s -> !s.equals(areaCode) && s.startsWith(XzqhUtils.getRegionCodePrefix(areaCode))));

        // 查询这些最末级节点的下级节点
        List<String> childXzqhdmListByXzqhdmList = xzqhService.getChildAreaCodesByParentAreaCodeList(new ArrayList<>(areaCodeSet), true);
        areaCodeSetCache.addAll(childXzqhdmListByXzqhdmList);
        return new ArrayList<>(areaCodeSetCache);
    }

    private MyTeamWorkAreaDTO createTeamWorkAreaInfo(SystemXzqh areaInfo) {
        MyTeamWorkAreaDTO myTeamWorkAreaDTO = new MyTeamWorkAreaDTO();
        myTeamWorkAreaDTO.setAreaCode(areaInfo.getXzqhdm());
        myTeamWorkAreaDTO.setAreaName(areaInfo.getXzqhqc());
        myTeamWorkAreaDTO.setShortAreaName(areaInfo.getXzqhmc());
        myTeamWorkAreaDTO.setAreaLevel(Integer.valueOf(areaInfo.getXzqhjb()));

        return myTeamWorkAreaDTO;
    }

    private MyTeamWorkAreaDTO createTeamWorkAreaInfo(XzqhDTO areaInfo) {
        MyTeamWorkAreaDTO myTeamWorkAreaDTO = new MyTeamWorkAreaDTO();
        myTeamWorkAreaDTO.setAreaCode(areaInfo.getXzqhdm());
        myTeamWorkAreaDTO.setAreaName(areaInfo.getXzqhqc());
        myTeamWorkAreaDTO.setShortAreaName(areaInfo.getXzqhmc());
        myTeamWorkAreaDTO.setAreaLevel(Integer.valueOf(areaInfo.getXzqhjb()));

        return myTeamWorkAreaDTO;
    }

    @Override
    public QRCodeInfoDTO getQRCodeInfo(GetProjectQRCodeInfoVO vo) throws Exception {
        validGenerateQRCodeParam(vo);
        return generateQRCodeInfo(vo);
    }

    /**
     * 校验生成二维码的参数
     * @param vo
     */
    private void validGenerateQRCodeParam(GetProjectQRCodeInfoVO vo) throws Exception {
        if (StrUtil.isNotBlank(vo.getProjectUuid())) {
            tProjectService.getProjectByUuid(vo.getProjectUuid());
        }
        if (StrUtil.isNotBlank(vo.getDepartmentId())) {
            departmentService.getDepartment(vo.getDepartmentId());
        }
    }

    /**
     * 生成二维码信息
     * @param vo
     * @return
     */
    private QRCodeInfoDTO generateQRCodeInfo(GetProjectQRCodeInfoVO vo) {
        QRCodeInfoDTO qrCodeInfoDTO = new QRCodeInfoDTO();
        qrCodeInfoDTO.setProjectUuid(vo.getProjectUuid());
        qrCodeInfoDTO.setDepartmentId(vo.getDepartmentId());
        qrCodeInfoDTO.setServiceUserType(vo.getQrCodeType());
        qrCodeInfoDTO.setQrCodeGenerateUserId(vo.getOperateUserId());
        return qrCodeInfoDTO;
    }

    /**
     * 扫描二维码保存项目服务人员
     * @param bo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageData qRCodeForSaveProjectServiceUser(QRCodeForSaveServiceUserBO bo) throws Exception {
        TProject project = tProjectService.getProjectByUuid(bo.getProjectUuid());

        // 服务人员扫码，需要根据二维码生成人ID，查询热链云对应的用户ID
        if (ProjectServiceUserTypeEnum.CONSTRUCTION_PERSONNEL.getKey().equals(bo.getServiceUserType())) {
            TUser user = systemUserService.getUser(project.getCompanyId(), bo.getQrCodeGenerateUserId());
            bo.setOperateUserId(user.getId());
            bo.setDepartmentId(user.getDepartmentId());
        } else {
            bo.setOperateUserId(bo.getQrCodeGenerateUserId());
        }

        // 组装数据
        SaveERUserBO saveERUserBO = bo.convertToERUserBO();
        saveERUserBO.setCompanyId(project.getCompanyId());
        saveERUserBO.setAreaCode(project.getAreaCode());
        // 处理易修用户和热链云用户关联
        TUser user = systemUserService.saveERUser(saveERUserBO);

        // 组装数据
        SaveProjectServiceUserBO saveProjectServiceUserBO = bo.convertToSaveBO();
        saveProjectServiceUserBO.setServiceUserId(user.getId());
        saveProjectServiceUserBO.setCompanyId(user.getCompanyId());
        saveProjectServiceUserBO.setEnableIdentity(1);
        // 保存项目服务人员
        try {
            this.saveProjectServiceUser(saveProjectServiceUserBO);
        } catch (Exception e) {
            return PageData.error(e.getMessage());
        }
        return PageData.ok();
    }

    /**
     * 获取用户的施工负责人权限
     * @param easyRepairUserId 易修用户ID
     * @return
     */
    @Override
    public List<ProjectServiceUserAuth> getHeadAuth(Long easyRepairUserId) throws Exception {
        if (ObjectUtil.isEmpty(easyRepairUserId)) {
            throw new MissBusinessParameterException("easyRepairUserId must not be null");
        }
        List<TUser> users = systemUserService.getUsers(easyRepairUserId);
        if (CollUtil.isEmpty(users)) {
            return Collections.emptyList();
        }
        List<Long> serviceUserIds = users.stream().map(TUser::getId).collect(Collectors.toList());
        QueryWrapper<ProjectServiceUserAuth> wrapper = new QueryWrapper<>();
        wrapper.in("service_user_id", serviceUserIds);
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        wrapper.eq("service_user_type", ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey());
        wrapper.eq("enable_identity", ProjectServiceUserEnableEnum.enable.getKey());
        return this.list(wrapper);
    }

    /**
     * 校验用户是否具有施工负责人权限
     * @param easyRepairUserId 易修用户ID
     * @return
     */
    @Override
    public boolean validateHeadAuth(Long easyRepairUserId) throws Exception {
        if (CollUtil.isEmpty(getHeadAuth(easyRepairUserId))) {
            return false;
        }
        return true;
    }

    /**
     * 设置项目服务人员行政区划
     * @param bo
     */
    @Override
    public void setProjectServiceUserAreaCode(SetProjectServiceUserAreaCodeBO bo) throws Exception {
        // 校验要设置的服务区域的项目服务人员
        ProjectServiceUserAuth projectServiceUserAuth = this.getById(bo.getProjectServiceUserAuthId());
        validateProjectServiceUserAuth(projectServiceUserAuth);

        // 校验操作人是否为项目负责人
        TUser user = systemUserService.getUser(projectServiceUserAuth.getCompanyId(), bo.getOperateUserId());
        ProjectServiceUserAuth projectHeadServiceUser = this.validHeadAuth(projectServiceUserAuth.getProjectUuid(), projectServiceUserAuth.getDepartmentId(), user.getId());
        bo.setOperateUserId(projectHeadServiceUser.getServiceUserId());

        // 查询施工负责人的服务区域行政区划代码
        List<String> headServiceUserAreaCodes = projectServiceUserAreaCodeService.getServiceAreaCodes(projectHeadServiceUser.getId());
        if (CollUtil.isEmpty(headServiceUserAreaCodes)) {
            throw new BusinessException("施工负责人未设置服务区域");
        }
        // 校验行政区划是否符合设置范围
        validatedServiceAreaCode(headServiceUserAreaCodes, bo.getAreaCodeList());

        // 设置项目服务人员的服务区域
        if (CollUtil.isNotEmpty(bo.getAreaCodeList())) {
            SetServiceUserAreaCodeBO setServiceUserAreaCodeBO = new SetServiceUserAreaCodeBO();
            BeanUtils.copyProperties(bo, setServiceUserAreaCodeBO);
            setServiceUserAreaCodeBO.setAuthId(projectServiceUserAuth.getId());
            setServiceUserAreaCodeBO.setAreaCodeList(bo.getAreaCodeList());
            projectServiceUserAreaCodeService.setAreaCode(setServiceUserAreaCodeBO);
        }
    }

    /**
     * 校验服务区域是否符合设置范围
     * @param serviceAreaCodes  服务区域范围
     * @param validateAreaCodes 要校验的服务区域
     */
    private void validatedServiceAreaCode(List<String> serviceAreaCodes,
            List<String> validateAreaCodes) throws Exception {
        if (CollUtil.isEmpty(serviceAreaCodes)) {
            log.error("serviceAreaCodes must not empty");
            throw new MissBusinessParameterException("serviceAreaCodes must not empty");
        }
        if (CollUtil.isEmpty(validateAreaCodes)) {
            log.error("validateAreaCodes must not empty");
            throw new MissBusinessParameterException("validateAreaCodes must not empty");
        }
        List<String> unMatchAreaCodes = validateAreaCodes.stream()
                .filter(arecode -> !serviceAreaCodes.contains(arecode))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(unMatchAreaCodes)) {
            List<SystemXzqh> systemXzqhs = (List<SystemXzqh>) xzqhService.listByIds(unMatchAreaCodes);
            throw new BusinessException("服务区域不符合设置范围！[" + systemXzqhs.stream()
                    .map(SystemXzqh::getXzqhmc)
                    .collect(Collectors.joining(",")) + "]");
        }
    }

    /**
     * 校验服务人员权限是否为施工负责人权限
     * @param projectServiceUserAuth 服务人员权限
     * @return
     */
    private boolean validHeadAuth(ProjectServiceUserAuth projectServiceUserAuth) {
        if (ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey()
                .equals(projectServiceUserAuth.getServiceUserType()) && ProjectServiceUserEnableEnum.enable.getKey()
                .equals(projectServiceUserAuth.getEnableIdentity())) {
            return true;
        }
        return false;
    }

    /**
     * 校验服务人员是否具有施工负责人权限
     * @param projectUuid   项目UUID
     * @param departmentId  部门ID
     * @param serviceUserId 服务人员ID
     * @return
     */
    private ProjectServiceUserAuth validHeadAuth(String projectUuid, String departmentId,
            Long serviceUserId) throws Exception {
        ProjectServiceUserAuth projectServiceUserAuth = this.getProjectServiceUserAuth(projectUuid, departmentId, serviceUserId);
        if (!this.validHeadAuth(projectServiceUserAuth)) {
            throw new BusinessException("不是施工负责人！");
        }
        return projectServiceUserAuth;
    }

    /**
     * 校验服务人员权限是否合法
     * @param projectServiceUserAuth 服务人员权限
     */
    private void validateProjectServiceUserAuth(ProjectServiceUserAuth projectServiceUserAuth) throws Exception {
        if (Objects.isNull(projectServiceUserAuth) || DeleteEnum._1.getKey() == projectServiceUserAuth.getDeleted()) {
            throw new IllegalBusinessException("项目服务人员不存在！");
        }
    }

    /**
     * 查询服务人员的服务权限
     * @param projectUuid   项目ID
     * @param departmentId  部门ID
     * @param serviceUserId 服务人员ID
     * @return
     */
    private ProjectServiceUserAuth getProjectServiceUserAuth(String projectUuid, String departmentId,
            Long serviceUserId) throws Exception {
        QueryWrapper<ProjectServiceUserAuth> wrapper = new QueryWrapper<>();
        wrapper.eq("project_uuid", projectUuid);
        wrapper.eq("department_id", departmentId);
        wrapper.eq("service_user_id", serviceUserId);
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        ProjectServiceUserAuth projectHeadServiceUserAuth = this.getOne(wrapper);
        if (ObjectUtil.isNull(projectHeadServiceUserAuth)) {
            throw new IllegalBusinessException("项目服务人员不存在！");
        }
        return projectHeadServiceUserAuth;
    }

    private List<ProjectServiceUserAuth> getProjectServiceUserAuths(Long serviceUserId,
            String projectUuid) throws Exception {
        QueryWrapper<ProjectServiceUserAuth> wrapper = new QueryWrapper<>();
        wrapper.eq("service_user_id", serviceUserId);
        if (StrUtil.isNotBlank(projectUuid)) {
            wrapper.eq("project_uuid", projectUuid);
        }
        wrapper.eq("enable_identity", ProjectServiceUserEnableEnum.enable.getKey());
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        return this.list(wrapper);
    }

    @Override
    public boolean validateBelongToTeam(Long userId, String projectUuid) throws Exception {
        List<ProjectServiceUserAuth> projectServiceUserAuths = this.getProjectServiceUserAuths(userId, projectUuid);
        return CollectionUtil.isNotEmpty(projectServiceUserAuths);
    }

    @Override
    public List<ProjectServiceUserDTO> getTeamUserAuthList(Long userId, String projectUuid) throws Exception {
        // 获取我的部门id
        Set<String> departmentIdSet = this.getDepartmentIdSetByAgent(userId, projectUuid);
        if (CollectionUtil.isEmpty(departmentIdSet)) {
            throw new IllegalBusinessException("未查询到我的项目服务配置的部门id");
        }
        return this.baseMapper.getProjectServiceUserList(projectUuid, departmentIdSet);
    }

    @Override
    public Set<Long> getTeamUserIdList(Long userId, String projectUuid, String areaCode) throws Exception {
        List<ProjectServiceUserDTO> teamUserList = this.getTeamUserAuthList(userId, projectUuid);
        if (CollectionUtil.isEmpty(teamUserList)) {
            throw new BusinessException("当前施工队没有任何成员!");
        }
        if (teamUserList.size() == 1 && teamUserList.get(0).getServiceUserId().equals(userId)) {
            throw new BusinessException("当前施工队没有其他队友!");
        }
        // 查这些人的全部行政区划
        Set<Long> myTeammateIdSet = new HashSet<>();
        for (ProjectServiceUserDTO projectServiceUserDTO : teamUserList) {
            if (projectServiceUserDTO.getServiceUserId().equals(userId)) {
                log.info("自己的服务信息不处理");
                continue;
            }
            List<String> serviceUserAllAreaCodes = this.getServiceUserAllAreaCodes(projectServiceUserDTO.getServiceUserId(), projectUuid);
            // 判断哪些满足查询条件
            if (serviceUserAllAreaCodes.stream().anyMatch(n -> areaCode.startsWith(XzqhUtils.getRegionCodePrefix(n)))) {
                myTeammateIdSet.add(projectServiceUserDTO.getServiceUserId());
            }
        }
        return myTeammateIdSet;
    }

    /**
     * 获取服务人员的全部行政区划
     * @param serviceUserId 服务人员ID
     * @return
     */
    public List<String> getServiceUserAllAreaCodes(Long serviceUserId) throws Exception {
        return this.getServiceUserAllAreaCodes(serviceUserId, null);
    }

    /**
     * 获取服务人员的全部行政区划
     * @param serviceUserId 服务人员ID
     * @param projectUuid   项目ID
     * @return
     */
    @Override
    public List<String> getServiceUserAllAreaCodes(Long serviceUserId, String projectUuid) throws Exception {
        if (ObjectUtil.isNull(serviceUserId)) {
            throw new MissBusinessParameterException("serviceUserId must not null");
        }
        return getServiceUserAllAreaCodes(this.getProjectServiceUserAuths(serviceUserId, projectUuid));
    }

    @Override
    public List<ProjectServiceUserAuth> getProjectServiceUsers(String projectUuid) throws Exception {
        if (StrUtil.isEmpty(projectUuid)) {
            throw new MissBusinessParameterException("projectUuid must not empty");
        }
        QueryWrapper<ProjectServiceUserAuth> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        wrapper.eq("enable_identity", ProjectServiceUserEnableEnum.enable.getKey());
        wrapper.eq("project_uuid", projectUuid);
        return this.list(wrapper);
    }

    @Override
    public boolean validateHeadAuth(Long userId, String projectUuid) {
        if (ObjectUtil.isNull(userId)) {
            throw new MissBusinessParameterException("userId must not null");
        }
        if (StrUtil.isEmpty(projectUuid)) {
            throw new MissBusinessParameterException("projectUuid must not empty");
        }
        QueryWrapper<ProjectServiceUserAuth> wrapper = new QueryWrapper<>();
        wrapper.eq("service_user_id", userId);
        wrapper.eq("project_uuid", projectUuid);
        wrapper.eq("service_user_type", ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey());
        wrapper.eq("enable_identity", ProjectServiceUserEnableEnum.enable.getKey());
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        return this.count(wrapper) > 0;
    }

    @Override
    public TUser getMyCaptain(Long userId, String projectUuid) throws Exception {
        List<ProjectServiceUserDTO> teamUserList = this.getTeamUserAuthList(userId, projectUuid);
        if (CollectionUtil.isEmpty(teamUserList)) {
            throw new BusinessException("当前施工队没有任何成员!");
        }
        if (teamUserList.size() == 1 && teamUserList.get(0).getServiceUserId().equals(userId)) {
            throw new BusinessException("当前施工队没有其他队友!");
        }
        // 拿到施工队长用户id
        Long captainUserId = teamUserList.stream()
                .filter(n -> ProjectServiceUserTypeEnum.CONSTRUCTION_MANAGER.getKey().equals(n.getServiceUserType()))
                .map(ProjectServiceUserDTO::getServiceUserId)
                .findFirst()
                .orElse(null);
        if (ObjectUtil.isNull(captainUserId)) {
            throw new BusinessException("您在当前项目没有施工队长");
        }
        // 查询施工队长用户信息
        TUser captainUserInfo = systemUserService.getUserInfoByUserId(String.valueOf(captainUserId));
        if (ObjectUtil.isNull(captainUserInfo)) {
            throw new BusinessException("您在当前项目没有施工队长");
        }
        return captainUserInfo;
    }

    /**
     * 获取服务人员的全部行政区划
     * @param projectServiceUserAuthList
     * @return
     */
    private List<String> getServiceUserAllAreaCodes(
            List<ProjectServiceUserAuth> projectServiceUserAuthList) throws Exception {
        if (CollUtil.isEmpty(projectServiceUserAuthList)) {
            return Collections.emptyList();
        }

        List<Long> authIds = projectServiceUserAuthList.stream()
                .map(ProjectServiceUserAuth::getId)
                .collect(Collectors.toList());
        List<String> allAreaCodes = new ArrayList<>();
        for (Long authId : authIds) {
            allAreaCodes.addAll(projectServiceUserAreaCodeService.getServiceAreaCodes(authId));
        }
        return allAreaCodes.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 根据易修用户id & 项目id查询 部门id
     */
    private Set<String> getDepartmentIdSetByEasyRepair(Long easyRepairUserId, String projectUuid) throws Exception {
        if (ObjectUtil.isNull(easyRepairUserId)) {
            throw new MissBusinessParameterException("easyRepairUserId must not null");
        }
        if (StrUtil.isBlank(projectUuid)) {
            throw new MissBusinessParameterException("projectUuid must not empty");
        }
        List<TUser> users = systemUserService.getUsers(easyRepairUserId);
        if (CollectionUtil.isEmpty(users)) {
            return Collections.emptySet();
        }
        Set<String> departmentIdSet = new HashSet<>();
        for (TUser user : users) {
            Set<String> departmentIdListByAgent = this.getDepartmentIdSetByAgent(user.getId(), projectUuid);
            departmentIdSet.addAll(departmentIdListByAgent);
        }
        return departmentIdSet;
    }

    /**
     * 根据热链云用户id & 项目id 查询部门id
     */
    private Set<String> getDepartmentIdSetByAgent(Long userId, String projectUuid) throws Exception {
        if (ObjectUtil.isNull(userId)) {
            throw new MissBusinessParameterException("userId must not null");
        }
        if (StrUtil.isBlank(projectUuid)) {
            throw new MissBusinessParameterException("projectUuid must not empty");
        }
        // 查询我的项目服务配置信息
        List<ProjectServiceUserAuth> projectServiceUserAuths = this.getProjectServiceUserAuths(userId, projectUuid);
        if (CollectionUtil.isEmpty(projectServiceUserAuths)) {
            return Collections.emptySet();
        }
        return projectServiceUserAuths.stream()
                .filter(ObjectUtil::isNotNull)
                .map(ProjectServiceUserAuth::getDepartmentId)
                .collect(Collectors.toSet());
    }

    /**
     * 查询用户服务范围是否符合行政区划的范围
     */
    private boolean checkServiceUserByAreaCode(ProjectServiceUserDTO projectServiceUserDTO, String areaCode) {
        final boolean VALID = true;
        final boolean UN_VALID = false;

        if (StrUtil.isBlank(areaCode) || ObjectUtil.isNull(projectServiceUserDTO)) {
            return VALID;
        }

        // 查询当前服务人员负责的全部行政区划代码
        try {
            List<String> serviceAreaCodes = projectServiceUserAreaCodeService.getServiceAreaCodes(projectServiceUserDTO.getId());
            if (CollectionUtil.isEmpty(serviceAreaCodes)) {
                return VALID;
            }

            // 如果直接命中负责的行政区划
            if (serviceAreaCodes.contains(areaCode)) {
                return VALID;
            }

            Set<String> serviceAreaCodeSet = new HashSet<>();
            // 从一级行政区划代码开始逐级比较
            for (int checkLevel = 1; checkLevel <= XzqhUtils.getRegionLevel(areaCode); checkLevel++) {
                String paramAreaCode = XzqhUtils.getParentRegionCode(areaCode, checkLevel);

                // 给lambda表达式准备参数
                final String finalParamAreaCode = paramAreaCode;

                // 寻找与入参行政区划代码同根的集合
                serviceAreaCodeSet = serviceAreaCodes.stream()
                        .filter(n -> n.startsWith(XzqhUtils.getRegionCodePrefix(finalParamAreaCode)))
                        .collect(Collectors.toSet());

                // 如果命中唯一的根节点
                if (serviceAreaCodeSet.size() == 1 && serviceAreaCodeSet.contains(paramAreaCode)) {
                    return VALID;
                }

                // 一个也没匹配上就直接返回不符合
                if (CollectionUtil.isEmpty(serviceAreaCodeSet)) {
                    return UN_VALID;
                }
            }
            return VALID;
        } catch (Exception e) {
            log.info("校验服务人员行政区划代码合法性异常!");
            return false;
        }
    }

}
